/* c't Mikrocontroller-im-LAN Demo Source
 * Datei: key.c
 * Info: Routinen zum Einlesen der Taster
 * Autor: Benjamin Benz (bbe@heise.de)
 * Datum: 24.06.04
 * Ergaenzungen von Marcus von Cube (marcus@mvcsys.de)
*/

#include <avr/io.h>
#include <avr/delay.h>
#include "key.h"
#include "led.h"
#include "tools.h"

unsigned char old_keys;

/*
 *  Liest den Port mit den Tasten ohne Entprellung und Flankenerkennung
 */
unsigned char key_port( void )
{
    unsigned char old_DDRD = DDRD;   // Alte Einstellungen sichern
    unsigned char old_PORTD = PORTD;
    unsigned char result;

    DDRD &= ~KEY_ALL;       // Alle Key-Ports als Input
    PORTD |= KEY_ALL;       // Alle Pullups an.

    result = PIND;

    PORTD = old_PORTD;
    DDRD = old_DDRD;        // wiederherstellen

    return ~result & KEY_ALL;
}


/*
 *  Liest alle Tasten aus. Wartet bis zu timeout
 *  und kehrt dann auch zurueck, wenn keine Aenderung erfolgt ist.
 */
unsigned char key_read( unsigned char timeout )
{
    unsigned char keys = 0;
    unsigned char temp;
    unsigned char i, j, k;

    k = 0; i = 0;

    /*
     *  solange warten, bis Taste gedrueckt
     */
    while ( keys == 0 && i < timeout )
    {
        /*
         *  Innenzaehler erhoehen
         *  Bei 8-Bit-Ueberlauf: Aussenzaehler erhoehen
         */
        ++k;
        if ( k == 0 ) ++i;

        /*
         *  Aenderungen einlesen
         */
        temp = key_port();
        keys = ( old_keys ^ temp ) & temp;
        old_keys = temp;

        if ( keys != 0 ) {
            /*
             *  Warten und zum Entprellem nochmal lesen
             */
            for ( j = 0; j < 255; j++ );
            keys &= key_port();
        }
    }

    if ( i == timeout ) {
        return KEY_TIMEOUT;
    }
    return keys;
}
